package com.apestech.api.condition;

import com.apestech.framework.db.SqlSession;
import com.apestech.framework.dictionary.modul.Table;
import com.apestech.framework.json.JSONObject;
import com.apestech.framework.util.StringUtil;
import com.apestech.framework.xml.condition.modul.Condition;
import com.apestech.framework.xml.condition.modul.Dimension;
import com.apestech.framework.xml.table.modul.Tables;
import java.util.ArrayList;

public class ConditionUpdateTable extends StringUtil {

    public class DifferentStau{
        private boolean struc=false;
        private boolean del=false;
        private boolean add=false;

        public boolean isStruc() {
            return struc;
        }

        public void setStruc(boolean struc) {
            this.struc = struc;
        }

        public boolean isDel() {
            return del;
        }

        public void setDel(boolean del) {
            this.del = del;
        }

        public boolean isAdd() {
            return add;
        }

        public void setAdd(boolean add) {
            this.add = add;
        }
    }

    private Condition condition;
    private SqlSession session;
    private boolean bmaster=false;

    public ConditionUpdateTable(Condition condition){
        this.condition=condition;
        this.session=condition.getSession();
    }

    public void updateTable(ConditionExec conditionExec) throws Exception {
        /*
        当前表是否存在数据，如果无数据，直接重新创建，否则走备份机制
        1.将现有表重命名方式备份
        2.创建新表
        3.将备份表数据COPY至新表（如果存在明细字段换成主表字段情况，只COPY对应EXEC表，没有生成执行表的单据保留备份数据，以备后续人工处理）
        4.判断master移动的方式：
             加master：明细维度字段减少
             去master：主表维度字段减少
        */
        //XML配置为主，与当前数据库里的实体表做对比
        //将正式命名表与备份表做对比，插入数据来源为备份表
        ArrayList<Dimension> dimensions=condition.getDimension();
        int len=dimensions.size();
        for(int i=0; i<len; i++){
            String mid=dimensions.get(i).getId();
            String tabName=condition.getTableKey().getTabName(mid);
            Tables ttab=condition.getTablesById(tabName);
            String tabId=ttab.getMasterTableId();
            if(session.tableExists(tabId)){
                String mtabId=tabId+"_ITEM";
                String ztabId=tabId+"_EXEC";
                String btabId=tabId+"_T";
                String bmtabId=btabId+"_ITEM";
                String bztabId=btabId+"_EXEC";
//                session.getForDDL().renameTable(tabId, btabId);
//                session.getForDDL().renameTable(mtabId, bmtabId);
//                session.getForDDL().renameTable(ztabId, bztabId);
                conditionExec.createTable(ttab);
                Table tab=session.getDictTable(tabId);
                Table mtab=session.getDictTable(mtabId);
                Table ztab=session.getDictTable(ztabId);
                Table btab=session.getDictTable(btabId);
                Table bmtab=session.getDictTable(bmtabId);
                Table bztab=session.getDictTable(bztabId);
                DifferentStau differentStau=getTableDifference(btab, tab, mid);
                String sql;
                if(!differentStau.isAdd()){
                    sql=getCompareSql(tab, btab, bmtab, btabId, bmtabId);
                    session.getForUpdate().insertTable(tabId, sql, new JSONObject());
                    sql=getCompareSql(mtab, btab, bmtab, btabId, bmtabId);
                    session.getForUpdate().insertTable(mtabId, sql, new JSONObject());
                }
                getTableDifference(bmtab, mtab, mid);
                getTableDifference(bztab, ztab, mid);
                sql=getTableSql(session.getDictTable(bztabId), session.getDictTable(ztabId), bztabId);
                session.getForUpdate().insertTable(ztabId, sql, new JSONObject());
            }
        }
    }

    private DifferentStau getTableDifference(Table stab, Table dtab, String mid) throws Exception {
        DifferentStau differentStau=new DifferentStau();
        ArrayList<String> msg=new ArrayList<String>();
        ArrayList<String> skey=stab.getField().getKeylist();
        ArrayList<String> dkey=dtab.getField().getKeylist();
        int slen=skey.size();
        int dlen=dkey.size();
        if(slen!=dlen){
            msg.add("表对应字段数不同：源表["+slen+"] 目标表["+dlen+"]");
        }
        for(int i=0; i<dlen; i++){
            String k=dkey.get(i);
            String dDbType=dtab.getField(k).getDbType();
            if(skey.contains(k)){
                String sDbType=stab.getField(k).getDbType();
                if(!dDbType.equals(sDbType)){
                    msg.add("源表与目标表对应字段["+k+"]类型不同，源["+sDbType+"]，目标["+dDbType+"]");
                    differentStau.setStruc(true);
                }
            } else {
                msg.add("目标表新加字段["+k+"] type["+dDbType+"]");
                if(condition.getDimensionById(mid).getField(k)!=null){
                    differentStau.setAdd(true);
                }
            }
        }
        for(int i=0; i<slen; i++){
            String k=skey.get(i);
            if(!dkey.contains(k)){
                String sDbType=stab.getField(k).getDbType();
                msg.add("目标表删减字段["+k+"] type["+sDbType+"]");
                differentStau.setDel(true);
            }
        }
        int len=msg.size();
        if(msg.size()>0){
            for(int i=0; i<len; i++){
                System.out.println(msg.get(i));
            }
        }
        return differentStau;
    }

    private String getTableSql(Table stab, Table dtab, String dTabId){
        ArrayList<String> skey=stab.getField().getKeylist();
        ArrayList<String> dkey=dtab.getField().getKeylist();
        String select="";
        int len=dkey.size();
        for(int i=0; i<len; i++){
            String k=dkey.get(i);
            if(skey.contains(k)){
                if(!"".equals(select)){
                    select=select+",";
                }
                select=select+"A."+k;
            } else {
                System.out.println("目标表新加字段["+k+"]");
                String defaultValue=dtab.getField(k).getColumnDef();
                if(defaultValue!=null){
                    if(!"".equals(select)){
                        select=select+",";
                    }
                    select=select+"'"+defaultValue+"' AS "+k;
                }
            }
        }
        if(!"".equals(select)){
            return "SELECT "+select+" FROM "+dTabId+" A WHERE 1=1 ";
        }
        return null;
    }

    private String getCompareSql(Table tab, Table btab, Table bmtab, String btabId, String bmtabId) throws Exception {
        ArrayList<String> key=tab.getField().getKeylist();
        ArrayList<String> bkey=btab.getField().getKeylist();
        ArrayList<String> bmkey=bmtab.getField().getKeylist();
        int len=key.size();
        String zselect = "";
        String mselect = "";
        for(int i=0; i<len; i++){
            String k=key.get(i);
            String dDbType=tab.getField(k).getDbType();
            if(bkey.contains(k)){
                String sDbType=btab.getField(k).getDbType();
                if(!dDbType.equals(sDbType)){
                    System.out.println("源表与目标表对应字段["+k+"]类型不同，源["+btabId+"表"+sDbType+"]，目标["+dDbType+"]");
                }
                if(!zselect.equals("")){
                    zselect = zselect +",";
                }
                zselect = zselect +"A."+k;
            } else if(bmkey.contains(k)){
                String sDbType=bmtab.getField(k).getDbType();
                if(!dDbType.equals(sDbType)){
                    System.out.println("源表与目标表对应字段["+k+"]类型不同，源["+bmtabId+"表"+sDbType+"]，目标["+dDbType+"]");
                }
                if(!mselect.equals("")){
                    mselect = mselect +",";
                }
                mselect = mselect +"B."+k;
            } else {
                String defaultValue=tab.getField(k).getColumnDef();
                if(defaultValue!=null){
                    if(!"".equals(zselect)){
                        zselect=zselect+",";
                    }
                    zselect=zselect+"'"+defaultValue+"' AS "+k;
                }
            }
        }
        String select="";
        String from="";
        if(!zselect.equals("")){
            select=" SELECT "+zselect;
            from=btabId+" A";
        }
        if(!mselect.equals("")){
            if("".equals(select)){
                select=" SELECT "+mselect;
                from=bmtabId+" B";
            } else {
                select=select+","+mselect;
                from=from+","+bmtabId+" B";
            }
        }
        String sql=select+" FROM "+from+" WHERE 1=1 ";
        return sql;
    }

}
